package com.medical.system.filter;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.medical.system.common.Result;
import com.medical.system.custom.CustomUser;
import com.medical.system.util.JwtHelper;
import com.medical.system.util.ResponseUtil;
import com.medical.system.vo.LoginVo;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @ 类的描述 : 自定义登录过滤器，校验用户是否登录成功，然后响应token
 * @ 作者 : 风花雪月
 * @ 时间 : 2024/7/23 21:38
 * @ 参数 :
 * @return:
 **/
public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {

    private RedisTemplate redisTemplate;


    public TokenLoginFilter(AuthenticationManager authenticationManager, RedisTemplate redisTemplate) {
        this.setAuthenticationManager(authenticationManager);
        this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/admin/system/index/login", "POST"));
        this.setPostOnly(false);
        this.redisTemplate = redisTemplate;
    }

    /**
     * @ 方法描述 : 登录验证，
     * @ 作者 : 风花雪月
     * @ 时间 : 2024/7/23 21:46
     * @ 参数 : [request, response]
     * @return: org.springframework.security.core.Authentication
     **/
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        try {
            LoginVo loginVo = new ObjectMapper().readValue(request.getInputStream(), LoginVo.class);
            Authentication authenticationToken = new UsernamePasswordAuthenticationToken(loginVo.getUsername(), loginVo.getPassword());
//            authenticate 已验证真实
            return this.getAuthenticationManager().authenticate(authenticationToken);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @ 方法描述 :验证成功，响应一个登录token
     * @ 作者 : 风花雪月
     * @ 时间 : 2024/7/23 21:50
     * @ 参数 : [request, response, chain, authResult]
     * @return: void
     **/
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        CustomUser customUser = (CustomUser) authResult.getPrincipal();
        String token = JwtHelper.createToken(customUser.getSysUser().getId() + "", customUser.getSysUser().getUsername());
        //保存权限数据到redis缓存中
        redisTemplate.opsForValue().set(customUser.getUsername(), JSON.toJSONString(customUser.getAuthorities()));
//        记录登录日志
//        sysLoginLogService.recordLoginLog(customUser.getUsername(), 1, IpUtil.getIpAddress(request), "OK");
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        ResponseUtil.out(response, Result.ok(map));
    }
}
